package easycloud.ecs.config;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

import easycloud.ecs.api.IProvider;

public final class MonitorConfigUtils {

	private static final Log logger = LogFactory
			.getLog(MonitorConfigUtils.class);

	/**
	 * 
	 * @param statFile
	 * @return
	 * @throws ConfigException
	 */
	public static void readStatistics(Map<String, IProvider> providers, File dir)
			throws ConfigException {
		for (Entry<String, IProvider> entry : providers.entrySet()) {
			File statFile = new File(dir, entry.getKey() + ".stat.json");
			if (statFile.exists()) {
				ObjectMapper objectMapper = new ObjectMapper();
				JsonParser parser;
				try {
					parser = objectMapper.getJsonFactory().createJsonParser(
							statFile);
					ProviderStatistics statistics = parser
							.readValueAs(ProviderStatistics.class);
					entry.getValue().setProviderStatistics(statistics);
				} catch (JsonParseException e) {
					MonitorConfigUtils.logger.warn(
							"Parse provider statistics failed", e);
					throw new ConfigException(
							"Parse provider statistics failed");
				} catch (IOException e) {
					MonitorConfigUtils.logger.warn(
							"Read provider statistics failed", e);
					throw new ConfigException("Read provider statistics failed");
				}
			}
		}
	}

	/**
	 * 
	 * @param configFile
	 * @return
	 * @throws ConfigException
	 */
	public static MonitorConfig readConfig(File configFile)
			throws ConfigException {
		MonitorConfig config = null;
		if (configFile.exists()) {
			ObjectMapper objectMapper = new ObjectMapper();
			JsonParser parser;
			try {
				parser = objectMapper.getJsonFactory().createJsonParser(
						configFile);
				config = parser.readValueAs(MonitorConfig.class);
			} catch (JsonParseException e) {
				MonitorConfigUtils.logger
						.warn("Parse monitor config failed", e);
				throw new ConfigException("Parse monitor config failed");
			} catch (IOException e) {
				MonitorConfigUtils.logger.warn("Read monitor config failed", e);
				throw new ConfigException("Read monitor config failed");
			}
		}
		return config;
	}

	/**
	 * @param eTags
	 *            ;
	 * @param dir
	 * @return
	 * @throws ConfigException
	 */
	public static Map<IProvider, Map<String, String>> readETags(
			Map<String, IProvider> providers, File dir) throws ConfigException {
		Map<IProvider, Map<String, String>> result = new HashMap<IProvider, Map<String, String>>();
		for (Entry<String, IProvider> entry : providers.entrySet()) {
			File eTagFile = new File(dir, entry.getKey() + ".etag.json");
			if (eTagFile.exists()) {
				ObjectMapper objectMapper = new ObjectMapper();
				JsonParser parser;
				try {
					parser = objectMapper.getJsonFactory().createJsonParser(
							eTagFile);
					@SuppressWarnings("unchecked")
					Map<String, String> value = parser.readValueAs(Map.class);
					result.put(entry.getValue(), value);
				} catch (JsonParseException e) {
					MonitorConfigUtils.logger.warn(
							"Parse monitor config failed", e);
					throw new ConfigException("Parse etag file failed");
				} catch (IOException e) {
					MonitorConfigUtils.logger.warn(
							"Read monitor config failed", e);
					throw new ConfigException("Read etag file failed");
				}
			}
		}
		return result;
	}

	public static void writeProviderStatistics(Collection<IProvider> providers,
			File dir) throws ConfigException {
		for (IProvider provider : providers) {
			File statFile = new File(dir, provider.getName()
					+ ".stat.json");
			if (!statFile.exists()) {
				try {
					statFile.createNewFile();
				} catch (IOException e) {
					MonitorConfigUtils.logger.warn(
							"Create provider statistic failed", e);
					throw new ConfigException(
							"Create provider statistic failed");
				}
			}
			ObjectMapper objectMapper = new ObjectMapper();
			String value;
			try {
				value = objectMapper.writeValueAsString(provider.getProviderStatistics());
				FileUtils.write(statFile, value);
			} catch (JsonGenerationException e) {
				MonitorConfigUtils.logger.warn(
						"Parse provider statistic failed", e);
				throw new ConfigException("Parse provider statistic failed");
			} catch (JsonMappingException e) {
				MonitorConfigUtils.logger.warn(
						"Parse provider statistic failed", e);
				throw new ConfigException("Parse provider statistic failed");
			} catch (IOException e) {
				MonitorConfigUtils.logger.warn(
						"Save provider statistic failed", e);
				throw new ConfigException("Save provider statistic failed");
			}
		}
	}

	/**
	 * 
	 * @param config
	 * @throws ConfigException
	 */
	public static void writeConfig(MonitorConfig config, File dir)
			throws ConfigException {
		File configFile = new File(dir, "monitor.json");
		if (!configFile.exists()) {
			try {
				configFile.createNewFile();
			} catch (IOException e) {
				MonitorConfigUtils.logger.warn("Create monitor config failed",
						e);
				throw new ConfigException("Create monitor config failed");
			}
		}
		ObjectMapper objectMapper = new ObjectMapper();
		String value;
		try {
			value = objectMapper.writeValueAsString(config);
			FileUtils.write(configFile, value);
		} catch (JsonGenerationException e) {
			MonitorConfigUtils.logger.warn("Parse monitor config failed", e);
			throw new ConfigException("Parse monitor config failed");
		} catch (JsonMappingException e) {
			MonitorConfigUtils.logger.warn("Parse monitor config failed", e);
			throw new ConfigException("Parse monitor config failed");
		} catch (IOException e) {
			MonitorConfigUtils.logger.warn("Save monitor config failed", e);
			throw new ConfigException("Save monitor config failed");
		}

	}

	/**
	 * 
	 * @param etags
	 * @param dir
	 * @throws ConfigException
	 */
	public static void writeETags(Map<IProvider, Map<String, String>> eTags,
			File dir) throws ConfigException {
		for (Entry<IProvider, Map<String, String>> entry : eTags.entrySet()) {
			File eTagFile = new File(dir, entry.getKey().getName()
					+ ".etag.json");
			if (!eTagFile.exists()) {
				try {
					eTagFile.createNewFile();
				} catch (IOException e) {
					MonitorConfigUtils.logger
							.warn("Create etag file failed", e);
					throw new ConfigException("Create etag file failed");
				}
			}
			ObjectMapper objectMapper = new ObjectMapper();
			String value;
			try {
				value = objectMapper.writeValueAsString(entry.getValue());
				FileUtils.write(eTagFile, value);
			} catch (JsonGenerationException e) {
				MonitorConfigUtils.logger
						.warn("Parse monitor config failed", e);
				throw new ConfigException("Parse monitor config failed");
			} catch (JsonMappingException e) {
				MonitorConfigUtils.logger
						.warn("Parse monitor config failed", e);
				throw new ConfigException("Parse monitor config failed");
			} catch (IOException e) {
				MonitorConfigUtils.logger.warn("Save monitor config failed", e);
				throw new ConfigException("Save monitor config failed");
			}
		}
	}

	private MonitorConfigUtils() {

	}
}
